using StackExchange.Redis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Text.Json;

namespace TerritoryGame.Infrastructure.Data;

public interface IRedisService
{
    IDatabase GetDatabase();
    Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = null);
    Task<T?> GetAsync<T>(string key);
    Task<bool> DeleteAsync(string key);
    Task<bool> ExistsAsync(string key);
}

public class RedisService : IRedisService, IDisposable
{
    private readonly IConnectionMultiplexer _redis;
    private readonly IDatabase _database;
    private readonly ILogger<RedisService> _logger;

    public RedisService(IConfiguration configuration, ILogger<RedisService> logger)
    {
        _logger = logger;
        
        var redisConfig = new ConfigurationOptions
        {
            EndPoints = { configuration["Redis:Host"] ?? "monkeymeerkat.cn" },
            Password = configuration["Redis:Password"] ?? "QAZqaz123!",
            DefaultDatabase = 0,
            ConnectTimeout = 5000,
            SyncTimeout = 5000,
            ConnectRetry = 3
        };

        try
        {
            _redis = ConnectionMultiplexer.Connect(redisConfig);
            _database = _redis.GetDatabase();
            _logger.LogInformation("Redis连接成功");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Redis连接失败");
            throw;
        }
    }

    public IDatabase GetDatabase() => _database;

    public async Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = null)
    {
        try
        {
            var json = JsonSerializer.Serialize(value);
            return await _database.StringSetAsync(key, json, expiry);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Redis Set操作失败: {Key}", key);
            return false;
        }
    }

    public async Task<T?> GetAsync<T>(string key)
    {
        try
        {
            var value = await _database.StringGetAsync(key);
            if (value.HasValue)
            {
                return JsonSerializer.Deserialize<T>(value!);
            }
            return default;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Redis Get操作失败: {Key}", key);
            return default;
        }
    }

    public async Task<bool> DeleteAsync(string key)
    {
        try
        {
            return await _database.KeyDeleteAsync(key);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Redis Delete操作失败: {Key}", key);
            return false;
        }
    }

    public async Task<bool> ExistsAsync(string key)
    {
        try
        {
            return await _database.KeyExistsAsync(key);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Redis Exists操作失败: {Key}", key);
            return false;
        }
    }

    public void Dispose()
    {
        _redis?.Close();
        _redis?.Dispose();
    }
}
